package com.dragon.modules.yuegou.client.wechat.client.impl;

import com.dragon.modules.yuegou.client.wechat.client.WeChatPayClient;
import com.sgy.ysq.utils.MD5;
import com.sgy.ysq.wx.client.WeChatPayClient;
import com.sgy.ysq.wx.model.XmlUtil;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Service;
import tech.liuwu.wechat.client.PayClient;
import tech.liuwu.wechat.common.PayMap;

import javax.net.ssl.SSLContext;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.security.KeyStore;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

@Service
public class WeChatPayClientImpl implements WeChatPayClient {
    protected final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private PayClient client;

    private final ResourceLoader resourceLoader;

    public WeChatPayClientImpl(ResourceLoader resourceLoader){
        this.resourceLoader = resourceLoader;
    }

    @Override
    public PayMap unifiedorder(PayMap request) {
        request = client.unifiedOrder(request);
        return request;

    }

    @Override
    public PayMap orderQuery(PayMap request) {
        request = client.orderQuery(request);
        return request;
    }

    /**
     * 服务商支付退款
     * @param request
     * @return
     */
    @Override
    public boolean retundMatch(PayMap request) {
        String out_trade_no= request.getOutTradeNo();
        Integer refund_fee= request.getRefundFee();

        String nonceStr =request.getNonceStr();

        TreeMap<String,Object> parameters = new TreeMap<String,Object>();

        parameters.put("appid", request.getAppid());
        parameters.put("mch_id", request.getMchId());
        parameters.put("sub_mch_id", request.getString("sub_mch_id"));
        parameters.put("nonce_str", nonceStr);
        parameters.put("out_trade_no",out_trade_no);
        parameters.put("out_refund_no",out_trade_no);
        parameters.put("total_fee",request.getTotalFee());
        parameters.put("refund_fee",refund_fee);

        //签名
        String createSign = createSign(parameters,"F98F6B7VST47UJOO478ZDY9VB8W6O0SE");
        parameters.put("sign",createSign);
        String refundxml = XmlUtil.converterWX(createWXPAYPostParam(parameters));

        KeyStore keyStore  =null;
        FileInputStream instream = null;
        CloseableHttpResponse res = null;
        CloseableHttpClient httpclient = null;

        try {
            keyStore  = KeyStore.getInstance("PKCS12");

            Resource resource = resourceLoader.getResource("classpath:mchcert/apiclient_cert.p12");
            try (InputStream certStream = resource.getInputStream()) {
                keyStore.load(certStream, "1505108951".toCharArray());
            }

            SSLContext sslcontext = SSLContexts.custom()
                    .loadKeyMaterial(keyStore, "1505108951".toCharArray())
                    .build();
            // Allow TLSv1 protocol only
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                    sslcontext,
                    new String[] { "TLSv1" },
                    null,
                    SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
            httpclient= HttpClients.custom()
                    .setSSLSocketFactory(sslsf)
                    .build();

            HttpPost httppost = new HttpPost("https://api.mch.weixin.qq.com/secapi/pay/refund");
            System.out.println("executing request" + httppost.getRequestLine());

            StringEntity reqEntity = new StringEntity(refundxml, "UTF-8");
            httppost.setEntity(reqEntity);
            httppost.setHeader("Content-Type", "application/xml");

            res = httpclient.execute(httppost);

            HttpEntity entity = res.getEntity();
            logger.info(res.getStatusLine().toString());
            StringBuffer XML = new StringBuffer();
            if (entity != null) {
                logger.info("Response content length: " + entity.getContentLength());
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(entity.getContent()));
                String text;
                while ((text = bufferedReader.readLine()) != null) {
                    XML.append(text);
                }
            }
            logger.info("退款申请xml:------------------------------------" + XML.toString() + "");
            EntityUtils.consume(entity);
            Document document = DocumentHelper.parseText(XML.toString());
            Element root = document.getRootElement();
            logger.debug(root.toString());
            String return_code = XmlUtil.getText(root.element("return_code"));
            String result_code = XmlUtil.getText(root.element("result_code"));
            logger.debug("result_code===="+result_code);
            String refund_id = XmlUtil.getText(root.element("refund_id"));
            //返回成功 修改退款信息
            if("SUCCESS".equals(return_code)&&"SUCCESS".equals(result_code)){
                //将订单修改为已退款

                return true;
            }
        } catch(Exception e){
            logger.warn("微信退款异常--->" + e.getMessage(), e);
        }finally {
            if(instream!=null){
                try {
                    instream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(res!=null){
                try {
                    res.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(httpclient!=null){
                try {
                    httpclient.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return false;
    }

    private static Map<String, Object> createWXPAYPostParam(Map<String,Object> parameters){
        Map<String, Object> map = new TreeMap<String, Object>();
        Set es = parameters.entrySet();//所有参与传参的参数按照accsii排序（升序）
        Iterator it = es.iterator();
        while(it.hasNext()) {
            Map.Entry entry = (Map.Entry)it.next();
            String k = (String)entry.getKey();
            Object v = entry.getValue();
            map.put(k,v);
        }
        return map ;
    }

    @SuppressWarnings("rawtypes")
    private static String createSign(Map<String,Object> parameters,String key){
        StringBuffer sb = new StringBuffer();
        Set es = parameters.entrySet();//所有参与传参的参数按照accsii排序（升序）
        Iterator it = es.iterator();
        while(it.hasNext()) {
            Map.Entry entry = (Map.Entry)it.next();
            String k = (String)entry.getKey();
            Object v = entry.getValue();
            if(null != v && !"".equals(v)
                    && !"sign".equals(k) && !"key".equals(k)) {
                sb.append(k + "=" + v + "&");
            }
        }
        String sign = MD5.wxsign(sb.toString(),key, "utf-8").toUpperCase();
        return sign;
    }
}
